

#include "MyEngine.h"
#include "MyDefinitions.h"
#include "MyUniversal.h"
#include "MyMenu.h"
#include "MyGame.h"
#include "MyUniversal.h"
#include "MyInfobar.h"
#include "MyPlayer.h"

//constructor; set all variables to implit values, create subordinate objects
MyEngine::MyEngine(){		
	//basic initialization
	run = true;					//game is running
	fpsElapsedTime = 0;
	updateCount = 0;
	actEngineState = ES_MENU;	//actual state of engine; implicit=menu (intro)
	switchEngineState = true;	//flag of state switching
	//create all the objects needed for game
	actGame = new MyGame(this);		//create game object
	actMenu = new MyMenu(this);		//create menu object	
	//actIntro = new MyIntro(this);	//create intro object	
}

//Destructor; use method to deinit all the objects
MyEngine::~MyEngine(){  deinit(); 
#ifdef _DEBUG
	printf("destroyed engine\n");
#endif  
}

//initialize SDL, SDL_ttf, set screen properties, open font and start timers
void MyEngine::init(){
    //Initialize all SDL subsystems
	if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
		printf("ERROR: Could not initialize SDL. The program will now quit.\n");
		run = false;	}
    //Initialize SDL_ttf
    if( TTF_Init() == -1 ) {
		printf("ERROR: Could not initialize TTF. The program will now quit.\n");
		run = false;	}
    //Set up the screen
    screen = SDL_SetVideoMode( SCREEN_W, SCREEN_H, SCREEN_BPP, SDL_SWSURFACE ); 
	//If there was in error in setting up the screen
    if( screen == NULL ){   
		printf("ERROR: Could not initialize video mode. The program will now quit.\n");
		run = false;	}

	//Open the font
	#ifdef _WIN32
	font = TTF_OpenFont( "misc\\lazy_dog.ttf", 18 );	
	#else
	font = TTF_OpenFont( "misc/lazy_dog.ttf", 18 );
	#endif
    
    //If there was an error in loading the font
	if( font == NULL ){
		printf("ERROR: Could not initialize font. The program will now quit. (Font file missing?)\n");
		system("pause");
		run = false;	}	
	//init the window caption & icon

	#ifdef _WIN32
	SDL_Surface* tempIconSheet = load_image("misc\\window_icon3.png");
	#else
	SDL_Surface* tempIconSheet = load_image("misc/window_icon3.png");
	#endif

    SDL_WM_SetIcon(tempIconSheet, 0);
    SDL_WM_SetCaption( "Archer Legacy v0.68", "pp");
	//unload_surface(tempIconSheet);
	
	//init fps timer
	fpsElapsedTime = 0;
	switchingToEngineState = ES_MENU;	//actual state of engine; implicit=menu (intro)
}


//deinit all the objects the MyEngine needed
void MyEngine::deinit() 
{	
	//Close the font
	if (font) {	TTF_CloseFont( font );	}
	kill_game();
	kill_menu();
	unload_surface(screen);
}
/* This function updates and redraws the scene, according to the game state.
 * It also handles timing and time correction, takes care of (de)initialization
 * when changing game states, etc.
 * It also takes events from the event queue and hands them over to the
 * relevant subsystems of the game.*/

void MyEngine::update(Uint32 _t)
{	//safety quit
	if (!run) {return;}
	//if too little time elapsed since the last update, wait & skip the function body
	//if (actTimer->timer_get_ticks() < actTimer->timer_get_stamp()) { SDL_Delay(1); return; }
	//while the time for this update is not up
	/*while (actTimer->timer_get_ticks() > actTimer->timer_get_stamp()) 
	/*{******************/
		//if must switch current game state
		if (switchEngineState)
		{
			//once we switch state, set this flag to false    
			switchEngineState = false;			
			//decide what state to switch to
			switch (switchingToEngineState){	
			case ES_INTRO:
				{ 
				#ifdef _DEBUG
					 printf("switching to intro\n"); 
				#endif
				actEngineState = ES_INTRO;				
				//actIntro->init_intro();								    
				break;
				}
			case ES_MENU: 
				{ 
				#ifdef _DEBUG
					 printf("switching to menu\n"); 
				#endif
				kill_game();
				init_menu();			
				actEngineState = ES_MENU; 				
				break;
				}	
			case ES_GAME: 
				{ 
				#ifdef _DEBUG
					 printf("switching to game\n"); 
				#endif		
				kill_menu();
				init_game();
				actEngineState = ES_GAME; 			    
				break;
				}	
			case ES_QUIT: 
				{ 
				#ifdef _DEBUG
					 printf("quitting\n"); 
				#endif		
				run = false; 				
				return;
				break;
				}
			case ES_SPECIAL_SCREEN: 
				{
				#ifdef _DEBUG
					 printf("special screen\n"); 
				#endif
				actEngineState = ES_SPECIAL_SCREEN; 
				break;
				}
            default: break;
        }
		}

		//event used to interact with the program
		SDL_Event actEvent;
		//Event processing	
		while (SDL_PollEvent(&actEvent))
		{
			//If the user has [X]-ed out the window, quit the program
			if (actEvent.type == SDL_QUIT) run = false; 

			switch (actEngineState)
			{
				case ES_INTRO: 	{
				// Skip intro if mouse button is pressed during it
				//if (actEvent.type == SDL_MOUSEBUTTONDOWN) actIntro->skip_intro();
				break;
					}
				//Events are passed to MyGame class for additional testing
				case ES_GAME:	{	actGame->process_event(actEvent, _t); break;	}				
				//Events are handed to MyMenu class for additional testing
				case ES_MENU:	{	actMenu->process_event(actEvent); break;	}							
			}
		}
		//do the things that are not dependent on the incomming events
		if (actEngineState == ES_GAME)	{	actGame->draw_all(_t);	}
		//Events comming while in special screen will result to GS_MENU
		if (actEngineState == ES_SPECIAL_SCREEN) 
		{ 
			SDL_WaitEvent(&actEvent);
			if (actEvent.type == SDL_KEYDOWN) 
			{
				goto_gs(ES_MENU);
				return;
			}
		}

		//call the redraw function to update screen
		this->redraw();
	 
		//add current elapsed time to the counter
		fpsElapsedTime += _t;
		//Increment the frame counter
		updateCount++;
        
		//if second elapsed
		if (fpsElapsedTime > 1000) 
		{			
			//The frame rate as a string
			std::stringstream caption;
			caption << "Average Frames Per Second: " << updateCount;
			//Reset the caption of the window
		
			if (this->actEngineState == ES_GAME)
			{
				actGame->actInfobar->make_top_msg(caption.str().c_str());
				sprintf(actGame->actInfobar->enemies_killed_text, "%d", actGame->actPlayer->get_enemies_killed()); 
				sprintf(actGame->actInfobar->money_text, "%d", actGame->actPlayer->get_money());
			}
			//Restart the update timer > necessary for fps calc
			//fpsElapsedTime -= 1000;
			if (updateCount > 1000/STANDARD_FPS) SDL_Delay(1);
			fpsElapsedTime = 0;
			updateCount = 0;
		}	
	 }
//}*******************/

//flips the screen, thus redraws whole window
void MyEngine::redraw() { if (SDL_Flip(screen) == -1) run = false;}
//make the game state switch possible
void MyEngine::goto_gs(engineState _state) 
{ 
	switchEngineState = true; 
	switchingToEngineState = _state;
}			
//deinit for game objects
void MyEngine::kill_game(){
	if (actGame) 
	{
		actGame->clean_game();
		actGame = NULL;
	}
}
void MyEngine::kill_menu(){
	if (actMenu) 
	{
		delete(actMenu);
		actMenu = NULL;
	}
}
//init for game objects
void MyEngine::init_menu()
{
	if (!actMenu) actMenu = new MyMenu(this);
	actMenu->init_menu();
}
void MyEngine::init_game()
{
	if (!actGame) actGame = new MyGame(this);
	actGame->init_game(); 				
}
//encapsulation function for engine run state
bool MyEngine::is_running(){ return run; }  
